<?php
namespace app\common\lib;

use app\common\exception\MemberException;
use app\common\query\AgentTypeLevelCoinConfig;
use app\common\query\AgentTypeOffset;
use think\Db;

class Active
{
    private $conf = [];

    private $offset = [];

    private $agent_type;

    private $agent_id;

    private $level;

    private $up_level;

    private $error_msg = '注册败，代理中心';

    /**
     * Active constructor.
     * @param $level
     * @param bool $agent_id
     * @param bool $up_level
     */
    public function __construct($level, $agent_id, $up_level=false)
    {
        $this->level = $level;
        $this->agent_id = $agent_id;
        $this->up_level = $up_level;
        if (false !== $up_level) $this->error_msg = '升级失败，';

        $agent = Db::name('member')->field('agent_type_id')->where('mid',$agent_id)->find();
        $this->agent_type = $agent['agent_type_id'];

        $conf = collection(AgentTypeLevelCoinConfig::agentTypeConfig($this->agent_type))->toArray();
        $this->conf = array_combine(array_column($conf, 'id'), $conf);

        if(false !== $up_level) {
            $level = $up_level;
        }
        $this->offset = AgentTypeOffset::offsetConf($this->agent_type, $level);
    }

    /**
     * 激活配置
     * @return array
     * @throws MemberException
     */
    private function getConf()
    {
        $conf = [];
        if (! $this->conf[$this->level]['config']) {
            throw new MemberException('系统错误，请联系管理员！');
        }
        $conf['coin'] = $this->conf[$this->level];
        $conf['offset'] = $this->offset;
        if (false !== $this->up_level) {
            $up_conf = $this->conf[$this->up_level];
            if (! $up_conf['config']) {
                throw new MemberException('系统错误，请联系管理员！');
            }
            $up_conf['amount'] = $up_conf['amount'] - $conf['coin']['amount'];
            $conf['coin'] = $up_conf;
            $conf['offset'] = $this->offset;
        }
        return $conf;
    }

    /**
     * @param $is_offset
     * @return mixed
     */
    public function doActive($is_offset)
    {
        //激活配置
        $conf = $this->getConf();
        //代理中心货币
        $agent_coin = Db::name('member_coin')->where('mid', $this->agent_id)->select();
        $agent_coin = array_combine(array_column($agent_coin, 'coin_id'), $agent_coin);
        $dec =  $this->mathAmount($conf, $agent_coin, $is_offset);
        return $dec;
    }

    /**
     * @param $target_amount
     * @param $offset_conf
     * @param $coin
     * @return array
     * @throws MemberException
     */
    private function doOffset($target_amount, $offset_conf, $coin)
    {
        $amount = bcsub($target_amount, ($offset_conf['ratio'] / 100 * $target_amount));
        if (bcsub($coin[$offset_conf['origin']]['amount'], $amount) < 0) {
            throw new MemberException($this->error_msg.$offset_conf['origin_name'].'不足！');
        }
        return ['amount'=>$amount, 'coin_name'=>$offset_conf['origin_name'], 'coin_id'=>$offset_conf['origin']];
    }

    /**
     * @param $conf
     * @param $coin
     * @param $is_offset
     * @return mixed
     * @throws MemberException
     */
    private function mathAmount($conf, $coin, $is_offset)
    {
        $conf_amount = $conf['coin']['amount'];
        foreach ($conf['coin']['config'] as $v) {
            //实际金额
            $amount = $v['config'] / 100 * $conf_amount;
            if (1==$is_offset && null !== $conf['offset'] && $v['coin_id'] == $conf['offset']['target']) {
                $offset = $this->doOffset($amount, $conf['offset'], $coin);
                //抵扣之后
                $amount = $amount - $offset['amount'];
                $dec[$offset['coin_id']] = ['amount'=>$offset['amount'], 'coin_name'=>$offset['coin_name']];
            }
            //货币金额不足
            if (bcsub($coin[$v['coin_id']]['amount'], $amount) < 0) {
                throw new MemberException($this->error_msg.$v['coin_name'].'不足！');
            }
            $dec[$v['coin_id']] = ['amount'=>$amount, 'coin_name'=>$v['coin_name']];
        }
        return $dec;
    }

    /**
     * @param $mid
     * @param $is_offset
     * @return mixed
     */
    public function doUpgrade($mid, $is_offset)
    {
        $member_coin = Db::name('member_coin')->where('mid',$mid)->select();
        $member_coin = array_combine(array_column($member_coin, 'coin_id'), $member_coin);
        $conf = $this->getConf();
        return $this->mathAmount($conf, $member_coin, $is_offset);
    }
}